home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvipage
/
dvipage.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-11
|
49KB
|
2,422 lines
/*
* dvipage: DVI Previewer Program for Suns
*
* Neil Hunt (hunt@spar.slb.com)
*
* This program is based, in part, upon the program dvisun,
* distributed by the UnixTeX group, extensively modified by
* Neil Hunt at the Schlumberger Palo Alto Research Laboratories
* of Schlumberger Technologies, Inc.
*
* From the dvisun manual page entry:
* Mark Senn wrote the early versions of [dvisun] for the
* BBN BitGraph. Stephan Bechtolsheim, Bob Brown, Richard
* Furuta, James Schaad and Robert Wells improved it. Norm
* Hutchinson ported the program to the Sun. Further bug fixes
* by Rafael Bracho at Schlumberger.
*
* Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
* Anyone can use this software in any manner they choose,
* including modification and redistribution, provided they make
* no charge for it, and these conditions remain unchanged.
*
* This program is distributed as is, with all faults (if any), and
* without any warranty. No author or distributor accepts responsibility
* to anyone for the consequences of using it, or for whether it serves any
* particular purpose at all, or any other reason.
*
* $Log: dvipage.c,v $
* Revision 1.6 88/12/15 09:08:03 hunt
* Added iteration to gobble inputs in panning and magnifier.
*
* Revision 1.5 88/11/28 18:39:21 hunt
* Major rewrite for 4.0 and sparc architecture.
* Split up into multiple files for easier maintenance.
* Reads GF files as well as PXL files now.
*
* Revision 1.4 88/11/26 11:10:53 hunt
* Used varargs with *_prompt() functions for correct behaviour on a sun4.
*
* Revision 1.3 88/08/30 13:04:13 hunt
* Changed default cmap for darker looking letters.
*
* Revision 1.2 88/08/30 09:26:29 hunt
* Fixed problem pointed out by pell@rainier.UUCP
* (pell@rainier.se, enea!rainier!pell@uunet.UU.NET)
* so that opened files are closed on exec, and do not clutter up
* space in print spoolers which may be invoked
* to print the document.
*
* Revision 1.1 88/08/30 09:05:19 hunt
* Initial revision
*
* HISTORY
*
* 12 April 1988 - Neil Hunt
* Version 2.0 released for use.
*
* 11 April 1988 - Neil Hunt
* Applied fixes supplied by Rafael Bracho (Schlumberger Austin)
* for operation on Sun-4 workstations.
*
* Earlier history unavailable.
*/
#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <varargs.h>
#include <sys/param.h> /* For MAXPATHLEN */
#include <sys/stat.h>
#include <suntool/sunview.h>
#include <suntool/canvas.h>
#include <suntool/panel.h>
#include <suntool/icon.h>
#include "dvipage.h"
#include "dvi.h"
#define GOBBLE_PAN
#define GOBBLE_MAGNIFY
/*
* Forward functions.
* =================
*/
forward int main();
forward Notify_value page_paint();
forward Notify_value page_event();
forward int page_menu();
forward void page_magnify();
forward void page_pan();
forward bool goto_sheet();
forward bool goto_page();
forward bool init_dvi_file();
forward void close_dvi_file();
forward bool check_dvi_file();
forward bool read_postamble();
forward bool find_postamble_ptr();
forward bool process_page();
forward void set_font_num();
forward void set_char();
forward void set_rule();
forward void move_down();
forward void move_over();
forward char * a_prog_name;
forward char a_next();
forward char * a_arg();
forward double a_number();
forward int a_integer();
/*
* Internal data structures.
* ========================
*/
struct stack_entry /* stack entry */
{
int h, v, w, x, y, z; /* what's on stack */
};
/*
* Globals.
* =======
*/
int hconv, vconv; /* converts DVI units to pixels */
int num; /* numerator specified in preamble */
int den; /* denominator specified in preamble */
int mag; /* magnification specified in preamble */
struct font_entry *fontptr; /* font_entry pointer */
struct font_entry *hfontptr=NULL;/* font_entry pointer */
double page_w = PAGE_WIDTH; /* page width (inches) */
double page_h = PAGE_HEIGHT; /* page width (inches) */
int h; /* current horizontal position */
int hh; /* current horizontal position in pixels */
int v; /* current vertical position */
int vv; /* current vertical position in pixels */
bool pre_load = TRUE; /* preload the font descriptions? */
bool silent = FALSE; /* suppress messages */
bool show_page_frame = FALSE; /* show page window */
long postambleptr; /* Pointer to the postamble */
char *font_path; /* Font path name for search */
bool use_gf = USE_GF; /* Enable the use of GF fonts. */
bool use_pxl = USE_PXL; /* Enable the use of PXL fonts. */
bool use_pk = USE_PK; /* Enable the use of PK fonts. */
FILE *dvifp = NULL; /* File pointer */
struct stat stat_buf; /* For checking file changes. */
time_t mtime = 0;
char label[STRSIZE];
char pathname[STRSIZE] = ""; /* Complete path */
char directory[STRSIZE] = ""; /* Directory */
char filename[STRSIZE] = ""; /* File name */
char print_spooler[STRSIZE] = PRINT_SPOOLER; /* Print commands. */
char print_page_spooler[STRSIZE] = PRINT_PAGE_SPOOLER;
int last_sheet = 0; /* Sheet number of last page in file */
int file_sheet = 1; /* Position of file pointer */
int disp_sheet = 0; /* Current displayed page */
int disp_page = 0; /* Real Page number */
int sheet_page[MAX_SHEETS]; /* Page number of each sheet. */
long sheet_table[MAX_SHEETS]; /* pointers to start of each page in file */
int last_known_sheet = 0; /* Points to table at next unread sheet */
int resolution = 0; /* Assumed screen resolution for rendering */
int sampling = 0; /* Sample down sampling factor */
bool mono; /* Monochrome screen */
Frame disp_frame; /* Frame for display window. */
Canvas disp_canvas; /* Canvas for display window. */
struct mem_pixrect page_mpr; /* Page bitmap. */
struct pixrect *page_pr;
struct mem_pixrect sample_mpr; /* Sampled/filtered bitmap. */
struct pixrect *sample_pr;
int origin_x; /* Nominal origin of the dvi on the page */
int origin_y; /* Nominal origin of the dvi on the page */
int offset_x; /* Offsets of page in window. */
int offset_y; /* Offsets of page in window. */
int start_x; /* Starting position of page in the window */
int start_y; /* Starting position of page in the window */
int verbose; /* Flags for debugging. */
int mag_size_x = DEFAULT_MAG_SIZE_X; /* Magnifier parameters. */
int mag_size_y = DEFAULT_MAG_SIZE_Y;
int mag_border = DEFAULT_MAG_BORDER;
forward uchar cmap_red[];
forward uchar cmap_green[];
forward uchar cmap_blue[];
short icon_image[] =
{
/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
*/
0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001,
0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
0x8000,0x0000,0x00C0,0x0001,0x8000,0x0000,0x0338,0x0001,
0x8000,0x0000,0x0447,0x0001,0x8000,0x0000,0x1911,0xE001,
0x8000,0x0000,0x2888,0x9E01,0x8000,0x0000,0xC222,0x23C1,
0x8000,0x0001,0x4444,0x4479,0x8000,0x0007,0x1111,0x1117,
0x8000,0x0008,0x8888,0x8889,0x8000,0x0032,0x2222,0x2223,
0x8000,0x0044,0x4444,0x4445,0x8000,0x0191,0x1111,0x1111,
0x8000,0x0288,0x8888,0x888B,0x8000,0x0C22,0x2222,0x2225,
0x8000,0x1444,0x4444,0x4447,0x8000,0x6111,0x1111,0x1119,
0x8000,0xC888,0x8888,0x889B,0x8000,0xB222,0x2222,0x2235,
0x8000,0xCE44,0x4444,0x446B,0x8000,0x91D1,0x1111,0x11D5,
0x8000,0x88B8,0x8888,0x88AB,0x8000,0xAC2E,0x2222,0x2355,
0x8000,0xC345,0xC444,0x46AB,0x8000,0x9CD1,0x3111,0x1555,
0x8000,0xB338,0x8E88,0x8AA5,0x8000,0xE0C6,0x23E2,0x3559,
0x8000,0xC039,0x8474,0x56B1,0x8000,0xC006,0x611F,0x2D41,
0x8000,0x9001,0x9C89,0xDEA1,0x8001,0x0C00,0x6322,0xFD41,
0x8002,0x43E0,0x1CC4,0xBE81,0x8004,0x2C18,0x0331,0xFD01,
0x8008,0x3606,0x00C8,0xBB01,0x8031,0xC781,0x0032,0xF601,
0x8040,0x4CC1,0x0014,0xAC01,0x818C,0x9840,0xC021,0xD801,
0x8602,0xB208,0xB048,0xA801,0x9861,0x6788,0x4CC2,0xD001,
0xB011,0xCCD9,0xC0C4,0xA001,0xA30D,0x1817,0x60B1,0xC001,
0x9883,0x3E1C,0x590E,0xC001,0x8463,0x6270,0x4101,0x8001,
0x821F,0xC1D0,0xC100,0x0001,0x813F,0xB310,0xB200,0x0001,
0x81FC,0x5831,0x0200,0x0001,0x87F8,0x4021,0x0400,0x0001,
0x9F8C,0x3006,0xC400,0x0001,0x9E07,0x0C18,0x0800,0x0001,
0x8C00,0x83E8,0x1000,0x0001,0x8000,0x6106,0x2000,0x0001,
0x8000,0x18C0,0x4000,0x0001,0x8000,0x0430,0x8000,0x0001,
0x8000,0x0309,0x0000,0x0001,0x8000,0x0081,0x0000,0x0001,
0x8000,0x0062,0x0000,0x0001,0x8000,0x0014,0x0000,0x0001,
0x8000,0x0008,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001,
0x8000,0x0000,0x0000,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
};
DEFINE_ICON_FROM_IMAGE(icon, icon_image);
short hand[] =
{
0x0C00,0x1200,0x1200,0x1380,0x1240,0x7270,0x9248,0x924E,
0x9249,0x9249,0x9009,0x8001,0x4002,0x4002,0x2004,0x2004
};
mpr_static(hand_pr, 16, 16, 1, hand);
Cursor hand_cursor;
/*
* Functions.
* =========
*/
/*
* main:
* Interpret args, open windows, loop forever.
*/
int
main(argc, argv)
int argc;
char *argv[];
{
int f;
char opt;
char *slash;
char *extension;
Pixwin *pw;
bool fake_mono;
char *printer;
double set_origin_x;
double set_origin_y;
double set_start_x;
double set_start_y;
/*
* local initialisations.
*/
fake_mono = FALSE;
set_origin_x = 0.0;
set_origin_y = 0.0;
set_start_x = 0.0;
set_start_y = 0.0;
/*
* Customise this part for your local printer environment.
* ======================================================
*/
#ifdef SPAR_HACKS
/*
* Set local printer hacks.
*/
printer = getenv("PRINTER");
if(printer && strncmp(printer, "lw", 2) == 0)
{
sprintf(print_spooler,
"dvips -P%s %%s >/dev/null 2>/dev/null",
printer);
sprintf(print_page_spooler,
"dvips -P%s -f %%d -t %%d %%s >/dev/null 2>/dev/null",
printer);
}
else if(printer && strncmp(printer, "im", 2) == 0)
{
sprintf(print_spooler,
"dviimp -P%s %%s >/dev/null 2>/dev/null",
printer);
sprintf(print_page_spooler,
"dviimp -P%s -S %%d -E %%d %%s >/dev/null 2>/dev/null",
printer);
}
else
{
fprintf(stderr, "PRINTER environment not recognised:\n");
fprintf(stderr, " using `%s' to print files\n",
print_spooler);
fprintf(stderr, " using `%s' to print pages\n",
print_page_spooler);
}
if(verbose & DEBUG_PRINTER)
{
fprintf(stderr, "Using `%s' to print files\n",
print_spooler);
fprintf(stderr, "Using `%s' to print pages\n",
print_page_spooler);
}
#endif SPAR_HACKS
/*
* Find font path environment.
*/
if((font_path = getenv(FONT_PATH)) == NULL)
font_path = FONT_AREA;
/*
* Get cursor.
*/
hand_cursor = cursor_create(
CURSOR_IMAGE, &hand_pr,
CURSOR_XHOT, 5,
CURSOR_YHOT, 0,
CURSOR_OP, PIX_SRC ^ PIX_DST,
0);
/*
* Create a disp_frame.
*/
disp_frame = window_create(0, FRAME,
WIN_X, 300,
WIN_Y, 50,
WIN_WIDTH,
(int)(page_w * DEFAULT_COLOUR_RES /
DEFAULT_COLOUR_SAMPLING) + 10,
WIN_HEIGHT,
(int)(page_h * DEFAULT_COLOUR_RES /
DEFAULT_COLOUR_SAMPLING) + 20,
FRAME_ARGC_PTR_ARGV, &argc, argv,
FRAME_LABEL, DVIPAGE_LABEL,
FRAME_ICON, &icon,
0);
/*
* Create the disp_canvas.
*/
disp_canvas = window_create(disp_frame, CANVAS,
CANVAS_RETAINED, FALSE,
CANVAS_AUTO_CLEAR, FALSE,
CANVAS_FIXED_IMAGE, TRUE,
WIN_CURSOR, hand_cursor,
WIN_CONSUME_PICK_EVENTS,
WIN_NO_EVENTS,
LOC_DRAG,
WIN_MOUSE_BUTTONS,
LOC_WINENTER, /* Otherwise misses first event */
LOC_WINEXIT,
0,
WIN_CONSUME_KBD_EVENTS,
WIN_NO_EVENTS,
WIN_ASCII_EVENTS,
WIN_LEFT_KEYS, /* For Expose, Hide, Close etc. */
KBD_USE, /* Otherwise click to type doesn't work */
KBD_DONE,
0,
CANVAS_REPAINT_PROC, page_paint,
WIN_EVENT_PROC, page_event,
WIN_WIDTH, WIN_EXTEND_TO_EDGE,
WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
0);
/*
* Interpret args.
*/
f = 0;
while((opt = a_next(argc, argv)) != A_END)
{
switch(opt)
{
default:
fprintf(stderr, "%s: illegal flag -%c\n",
a_prog_name, opt);
/* FALLTHROUGH */
case 'H':
fprintf(stderr,
"Usage: %s \\\n", a_prog_name);
fprintf(stderr,
" [-v mode] # Verbose mode (for debugging) \\\n");
fprintf(stderr,
" [-m] # Force monochrome mode \\\n");
fprintf(stderr,
" [-p font-file-path] # List of font directories \\\n");
fprintf(stderr,
" [-P flag] # Enable or disable the use of PXL files \\\n");
fprintf(stderr,
" [-K flag] # Enable or disable the use of PK files \\\n");
fprintf(stderr,
" [-G flag] # Enable or disable the use of GF files \\\n");
fprintf(stderr,
" [-l] # Don't preload font data \\\n");
fprintf(stderr,
" [-q] # Quiet: no warning messages \\\n");
fprintf(stderr,
" [-f] # Show rendering frame on page \\\n");
fprintf(stderr,
" [-r res] # Use `res' dpi fonts \\\n");
fprintf(stderr,
" [-s sample] # Reduce by factor of `sample' \\\n");
fprintf(stderr,
" [-x x] [-y y] # Initial pos of sheet in inches \\\n");
fprintf(stderr,
" [-X ox] [-Y oy] # Pos of (0, 0) on page in inches \\\n");
fprintf(stderr,
" [-w width] [-h height] # Total size of page in inches \\\n");
fprintf(stderr,
" [dvifile[.dvi]]\n");
exit(1);
case 'v':
verbose = a_integer(argc, argv);
break;
case 'm':
fake_mono = TRUE;
break;
case 'p':
font_path = a_arg(argc, argv);
break;
case 'P':
use_pxl = a_integer(argc, argv);
break;
case 'K':
use_pk = a_integer(argc, argv);
break;
case 'G':
use_gf = a_integer(argc, argv);
break;
case 'l':
pre_load = ! pre_load;
break;
case 'q':
silent = ! silent;
break;
case 'f':
show_page_frame = ! show_page_frame;
break;
case 'r':
resolution = a_integer(argc, argv);
break;
case 's':
sampling = a_integer(argc, argv);
break;
case 'x':
set_start_x = a_number(argc, argv);
break;
case 'y':
set_start_y = a_number(argc, argv);
break;
case 'X':
set_origin_x = a_number(argc, argv);
break;
case 'Y':
set_origin_y = a_number(argc, argv);
break;
case 'w':
page_w = a_number(argc, argv);
break;
case 'h':
page_h = a_number(argc, argv);
break;
case A_ARG:
switch(f++)
{
case 0:
/*
* Get the whole pathname.
*/
strcpy(pathname, a_arg(argc, argv));
/*
* Get the filename and directory
*/
strcpy(directory, pathname);
if((slash = rindex(directory, '/')) != NULL)
{
strcpy(filename, slash+1);
*++slash = '\0';
}
else
{
directory[0] = '\0';
strcpy(filename, pathname);
}
/*
* If the filename has no extension, or if it
* has an extension and it is not '.dvi' then
* cat .dvi onto the filename.
*/
if((extension = rindex(pathname, '.')) == NULL ||
strcmp(extension, ".dvi") != 0)
strcat(pathname, ".dvi");
break;
default:
fprintf(stderr,
"%s: too many dvi files\n", a_prog_name);
exit(1);
}
break;
}
}
pw = canvas_pixwin(disp_canvas);
/*
* Now that we know whether we are on a colour machine or a monochrome,
* we can set the defaults for the resolution and sampling, unless
* they have already been set from the args.
*/
if(fake_mono || (pw->pw_pixrect->pr_depth == 1))
{
/*
* Monochrome
*/
mono = TRUE;
if(resolution == 0)
resolution = DEFAULT_MONO_RES;
if(sampling == 0)
sampling = DEFAULT_MONO_SAMPLING;
}
else
{
/*
* Colour
*/
mono = FALSE;
if(resolution == 0)
resolution = DEFAULT_COLOUR_RES;
if(sampling == 0)
sampling = DEFAULT_COLOUR_SAMPLING;
/*
* Compute and set a colour map
*/
make_cmap();
pw_setcmsname(pw, "dvipage-greys");
pw_putcolormap(pw, 0, 64, cmap_red, cmap_green, cmap_blue);
}
/*
* Now that we know the resolution and sampling, we can set
* the margin and origin properly.
*/
if(set_origin_x != 0.0)
origin_x = (int)(set_origin_x * resolution);
else
origin_x = (int)(DEFAULT_ORIGIN_X * resolution);
if(set_origin_y != 0.0)
origin_y = (int)(set_origin_y * resolution);
else
origin_y = (int)(DEFAULT_ORIGIN_Y * resolution);
if(set_start_x != 0.0)
start_x = (int)(set_start_x * resolution);
else
start_x = (int)(DEFAULT_START_X * resolution);
if(set_start_y != 0.0)
start_y = (int)(set_start_y * resolution);
else
start_y = (int)(DEFAULT_START_Y * resolution);
/*
* Insert the window into the heap now, so that if a message is
* generated by the init_dvi_file below, it is displayed after the
* window, and is therefore on top of it. If we display the window
* after doing the initialisation of the dvi file, it would obscure
* any error messages which might have been generated.
*/
window_set(disp_frame,
WIN_SHOW, TRUE,
0);
/*
* If we don't run the notifier at this time, the window will
* not be painted, and the effect will be a gross area of the
* screen which is not painted, through which the previous windows
* are still visible.
*/
notify_dispatch();
/*
* If there was a filename specified, then open it
* and prepare the first page.
*/
if(f >= 1)
{
/*
* Init the file.
*/
if(init_dvi_file())
{
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(disp_canvas, pw, 0);
}
}
else
getwd(directory);
/*
* Loop forever in the notifier.
*/
notify_start();
}
/*
* Window Functions.
* ================
*/
/*
* page_paint:
* Called whenever the window is to be painted.
* Just maps the sampled pixrect into the screen at the appropriate
* offset position.
*/
Notify_value
page_paint(canvas, pw, area)
Canvas canvas;
Pixwin *pw;
Rectlist *area;
{
if(sample_pr == NULL)
{
pw_rop(pw, 0, 0,
(int)window_get(canvas, WIN_WIDTH),
(int)window_get(canvas, WIN_HEIGHT),
PIX_CLR, NULL, 0, 0);
sprintf(label, "%s: No File", DVIPAGE_LABEL);
window_set(disp_frame,
FRAME_LABEL, label,
0);
}
else
{
pw_cover(pw, 0, 0,
(int)window_get(canvas, WIN_WIDTH),
(int)window_get(canvas, WIN_HEIGHT),
PIX_SRC, sample_pr, -offset_x, -offset_y);
sprintf(label, "%s: File \"%s\" %s %d",
DVIPAGE_LABEL, filename,
(last_sheet && disp_sheet >= last_sheet-1)?
"Last page" : "Page",
disp_page);
window_set(disp_frame,
FRAME_LABEL, label,
0);
}
}
/*
* page_event:
* Called whenever an input event arrives at the window.
* Controls panning of the page, turning to the next page,
* and reloading a new file.
*/
Notify_value
page_event(canvas, event, arg)
Window canvas;
Event *event;
caddr_t arg;
{
Pixwin *pw;
int e;
int pp;
bool page_or_sheet;
static int num = 0;
static bool valid_num = FALSE;
bool keep_num;
char *extension;
char command[STRSIZE];
double x, y;
if(event_is_up(event))
return;
pw = canvas_pixwin(canvas);
keep_num = FALSE;
if(verbose & DEBUG_SHEET)
fprintf(stderr, "page_event: num = %d @ %d\n", num, valid_num);
/*
* If there is a call for a menu, then translate that into
* a command character.
*/
if((e = event_id(event)) == MS_RIGHT)
if((e = page_menu(canvas, pw, event)) == 0)
return;
switch(e)
{
case MS_LEFT:
page_magnify(canvas, pw, event);
break;
case MS_MIDDLE:
page_pan(canvas, pw, event);
break;
default:
if(e >= '0' && e <= '9')
num = num * 10 + e - '0';
else if(e == DEL || e == Control('H'))
num = num / 10;
else
break;
keep_num = TRUE;
valid_num = TRUE;
break;
case '\r': /* Next page */
case 'n':
case ' ':
case '+':
if(! valid_num)
num = 1;
if(! goto_sheet(disp_sheet + num))
break;
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case '\n': /* Previous page */
case 'p':
case '-':
if(! valid_num)
num = 1;
if(! goto_sheet(disp_sheet - num))
break;
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case '_':
num = 1;
valid_num = TRUE;
/* FALLTHROUGH */
case 'G':
if(! valid_num)
num = LAST_PAGE;
if(! goto_sheet(num))
break;
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case 'g':
if(! valid_num)
num = LAST_PAGE;
if(! goto_page(num))
break;
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case 'h': /* Home page */
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case 'l': /* Left page */
offset_x -= 200;
page_paint(canvas, pw, 0);
break;
case 'r': /* Right page */
offset_x += 200;
page_paint(canvas, pw, 0);
break;
case 'u': /* Up page */
offset_y -= 300;
page_paint(canvas, pw, 0);
break;
case 'd': /* Down page */
offset_y += 300;
page_paint(canvas, pw, 0);
break;
case 'm': /* Mark margins */
start_x = offset_x * sampling;
start_y = offset_y * sampling;
break;
case 'M': /* Set margins */
x = ((double)start_x / resolution);
y = ((double)start_y / resolution);
if(! doubles_prompt(1152/2, 900/2,
"left margin: (inches) ", &x,
"top margin: (inches) ", &y,
0))
break;
start_x = (int)(x * resolution);
start_y = (int)(y * resolution);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case '*':
case '!':
case '@':
case '#':
case '$':
case '%':
case '^':
valid_num = TRUE;
if(e == '*')
num = (mono ?
DEFAULT_MONO_SAMPLING : DEFAULT_COLOUR_SAMPLING);
else if(e == '!')
num = 1;
else if(e == '@')
num = 2;
else if(e == '#')
num = 3;
else if(e == '$')
num = 4;
else if(e == '%')
num = 5;
else
valid_num = FALSE;
/* FALLTHROUGH */
case 's':
if(mono)
break;
if(! valid_num || (num < 1 || num > 5))
sampling = DEFAULT_COLOUR_SAMPLING;
else
sampling = num;
sample_page();
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case 'S':
if(mono)
break;
if(! integers_prompt(1152/2, 900/2,
"sampling: (1, 2, 3, 4) ", &sampling,
0))
break;
if(sampling < 1 || sampling > 5)
sampling = DEFAULT_COLOUR_SAMPLING;
sample_page();
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
break;
case 'x':
if(valid_num)
mag_size_x = num;
else
mag_size_x = DEFAULT_MAG_SIZE_X;
break;
case 'y':
if(valid_num)
mag_size_y = num;
else
mag_size_y = DEFAULT_MAG_SIZE_Y;
break;
case 'X':
case 'Y':
if(mono)
break;
if(! integers_prompt(1152/2, 900/2,
"magnifier size (x) : ", &mag_size_x,
"magnifier size (y) : ", &mag_size_y,
0))
break;
break;
case '[':
mag_size_x = 128;
mag_size_y = 64;
break;
case ']':
mag_size_x = 128;
mag_size_y = 128;
break;
case '{':
mag_size_x = 256;
mag_size_y = 128;
break;
case '}':
mag_size_x = 256;
mag_size_y = 256;
break;
case '(':
mag_size_x = 512;
mag_size_y = 256;
break;
case ')':
mag_size_x = 512;
mag_size_y = 512;
break;
case 'b':
if(valid_num)
mag_border = num;
else
mag_border = DEFAULT_MAG_BORDER;
break;
case 'F':
if(! strings_prompt(1152/2, 900/2,
"Directory: ", directory,
"Filename: ", filename,
0))
break;
/*
* Build the whole pathname.
*/
if(directory[0] != '\0')
{
strcpy(pathname, directory);
if(pathname[strlen(pathname)-1] != '/')
strcat(pathname, "/");
strcat(pathname, filename);
}
else
strcpy(pathname, filename);
/*
* If the filename has no extension, or if it
* has an extension and it is not '.dvi' then
* cat .dvi onto the filename.
*/
if((extension = rindex(pathname, '.')) == NULL ||
strcmp(extension, ".dvi") != 0)
strcat(pathname, ".dvi");
sprintf(label, "%s: Opening file \"%s\"",
DVIPAGE_LABEL, filename);
window_set(disp_frame,
FRAME_LABEL, label,
0);
close_dvi_file();
if(init_dvi_file())
{
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
}
break;
case 'R': /* Reopen file */
sprintf(label, "%s: Reopening file \"%s\"",
DVIPAGE_LABEL, filename);
window_set(disp_frame,
FRAME_LABEL, label,
0);
if(valid_num)
{
pp = num;
page_or_sheet = TRUE;
}
else
{
pp = disp_sheet;
page_or_sheet = FALSE;
}
close_dvi_file();
if(init_dvi_file())
{
if(page_or_sheet)
{
if(! goto_page(pp))
(void)goto_sheet(1);
}
else
{
if(! goto_sheet(pp))
(void)goto_sheet(1);
}
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
}
break;
case 'P':
sprintf(command, print_page_spooler,
disp_page, disp_page, pathname);
if(verbose & DEBUG_PRINTER)
fprintf(stderr, "Printer command '%s'\n", command);
system(command);
break;
case Control('P'):
sprintf(command, print_spooler, pathname);
if(verbose & DEBUG_PRINTER)
fprintf(stderr, "Printer command '%s'\n", command);
system(command);
break;
case 'w':
show_page_frame = ! show_page_frame;
if(goto_sheet(disp_sheet))
{
process_page(RASTERISE);
offset_x = start_x / sampling;
offset_y = start_y / sampling;
page_paint(canvas, pw, 0);
}
break;
case 'v':
if(valid_num)
verbose = num;
else
verbose = 0;
break;
case 'Q':
exit();
}
if(! keep_num)
{
num = 0;
valid_num = FALSE;
}
if(verbose & DEBUG_SHEET)
fprintf(stderr, "end__event: num = %d @ %d\n", num, valid_num);
}
/*
* page_menu:
* Displays a menu in response to MS_RIGHT, returns a character
* code to calling function to effect action.
*/
int
page_menu(canvas, pw, event)
Canvas canvas;
Pixwin *pw;
Event *event;
{
static Menu menu = NULL;
int action;
if(! menu)
{
/*
* Return values from this menu are passed to the
* event procedure, and the codes here must match
* codes in that function.
*/
menu = menu_create(
MENU_ITEM,
MENU_STRING, "Next Page",
MENU_VALUE, 'n',
0,
MENU_ITEM,
MENU_STRING, "Previous Page",
MENU_VALUE, 'p',
0,
MENU_ITEM,
MENU_STRING, "First Page",
MENU_VALUE, '_',
0,
MENU_ITEM,
MENU_STRING, "Last Page",
MENU_VALUE, 'G',
0,
MENU_ITEM,
MENU_STRING, "Sampling",
MENU_PULLRIGHT, menu_create(
MENU_ITEM,
MENU_STRING, "Default Sampling",
MENU_VALUE, '%',
0,
MENU_ITEM,
MENU_STRING, "No Sampling",
MENU_VALUE, '!',
0,
MENU_ITEM,
MENU_STRING, "2:1 Sampling",
MENU_VALUE, '@',
0,
MENU_ITEM,
MENU_STRING, "3:1 Sampling",
MENU_VALUE, '#',
0,
MENU_ITEM,
MENU_STRING, "4:1 Sampling",
MENU_VALUE, '$',
0,
0),
0,
MENU_ITEM,
MENU_STRING, "Magnifier",
MENU_PULLRIGHT, menu_create(
MENU_ITEM,
MENU_STRING, "128 x 64",
MENU_VALUE, '[',
0,
MENU_ITEM,
MENU_STRING, "128 x 128",
MENU_VALUE, ']',
0,
MENU_ITEM,
MENU_STRING, "256 x 128",
MENU_VALUE, '{',
0,
MENU_ITEM,
MENU_STRING, "256 x 256",
MENU_VALUE, '}',
0,
MENU_ITEM,
MENU_STRING, "512 x 256",
MENU_VALUE, '(',
0,
MENU_ITEM,
MENU_STRING, "512 x 512",
MENU_VALUE, ')',
0,
0),
0,
MENU_ITEM,
MENU_STRING, "Reopen DVI file",
MENU_VALUE, 'R',
0,
MENU_ITEM,
MENU_STRING, "New DVI file",
MENU_VALUE, 'F',
0,
/* MENU_ITEM,
MENU_STRING, "Print Page",
MENU_VALUE, 'P',
0,
MENU_ITEM,
MENU_STRING, "Print Document",
MENU_VALUE, Control('P'),
0, */
MENU_ITEM,
MENU_STRING, "Quit",
MENU_VALUE, 'Q',
0,
0);
}
return (int)menu_show(menu, canvas, event, 0);
}
/*
* page_magnify:
* Pops up magnified region (only if sampling != 1).
* Currently unimplemented.
*/
void
page_magnify(canvas, pw, event)
Canvas canvas;
Pixwin *pw;
Event *event;
{
Rect r;
int w, h;
double scale_x, scale_y;
int sample_w, sample_h;
int new_sample_x, new_sample_y;
int delta_x, delta_y;
int sample_x, sample_y;
int dst_x, dst_y;
int page_x, page_y;
int old_cursor_op;
bool first_time = TRUE;
int win_x, win_y;
#ifdef GOBBLE_MAGNIFY
int ninputs, canvasfd;
#endif GOBBLE_MAGNIFY
if(sampling == 1 || sample_pr == NULL)
return;
if(mag_size_x < 4)
mag_size_x = 4;
if(mag_size_y < 4)
mag_size_y = 4;
if(mag_size_x > sample_pr->pr_width)
mag_size_x = sample_pr->pr_width;
if(mag_size_y > sample_pr->pr_height)
mag_size_y = sample_pr->pr_height;
if(mag_border < 0)
mag_border = 0;
if(mag_border > 8)
mag_border = 8;
/*
* Get Lock rect.
*/
r.r_left = 0;
r.r_top = 0;
r.r_width = (int)window_get(canvas, WIN_WIDTH);
r.r_height = (int)window_get(canvas, WIN_HEIGHT);
/*
* Precompute some window sizes.
*/
w = sample_pr->pr_width;
h = sample_pr->pr_height;
switch(sampling)
{
case 2:
scale_x = 2.0;
scale_y = 2.0;
break;
case 3:
scale_x = 8.0 / 3.0;
scale_y = 3.0;
break;
case 4:
scale_x = 4.0;
scale_y = 4.0;
break;
case 5:
scale_x = 8.0/3.0;
scale_y = 4.0;
break;
default:
return;
}
sample_w = mag_size_x / scale_x;
sample_h = mag_size_y / scale_y;
if(verbose & DEBUG_MAGNIFY)
fprintf(stderr, "page_magnify: scale %lf %lf; %d %d -> %d %d\n",
scale_x, scale_y, sample_w, sample_h, mag_size_x, mag_size_y);
/*
* Remove the cursor
*/
old_cursor_op = (int)cursor_get(hand_cursor, CURSOR_OP);
cursor_set(hand_cursor, CURSOR_OP, PIX_DST, 0);
window_set(canvas, WIN_CURSOR, hand_cursor, 0);
/*
* Grab all input
*/
window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0);
#ifdef GOBBLE_MAGNIFY
canvasfd = (int)window_get(canvas, WIN_FD);
#endif GOBBLE_MAGNIFY
/*
* Loop until up mouse.
*/
sample_x = MAXINT;
sample_y = MAXINT;
while(! event_is_up(event))
{
/*
* Compute the region which will be magnified.
*/
new_sample_x =
Range(0, event_x(event)-offset_x-sample_w/2, w-sample_w);
new_sample_y =
Range(0, event_y(event)-offset_y-sample_h/2, h-sample_h);
/*
* See how this differs from last magnified region.
*/
delta_x = new_sample_x - sample_x;
delta_y = new_sample_y - sample_y;
/*
* Lock
*/
pw_lock(pw, &r);
if(! first_time)
{
if(verbose & DEBUG_MAGNIFY)
fprintf(stderr, " covering with %d %d\n",
delta_x, delta_y);
/*
* Paint those portions of the image which were
* covered by the last magnifier, and exposed now.
* We could just paint the entire patch, but this
* gives unpleasant flashing when moving the window.
*/
if(delta_x > 0)
pw_cover(pw, win_x, win_y,
delta_x, mag_size_y,
PIX_SRC, sample_pr, dst_x, dst_y);
else if(delta_x < 0)
pw_cover(pw, win_x+mag_size_x+delta_x, win_y,
-delta_x, mag_size_y,
PIX_SRC, sample_pr,
dst_x+mag_size_x+delta_x, dst_y);
if(delta_y > 0)
pw_cover(pw, win_x, win_y,
mag_size_x, delta_y,
PIX_SRC, sample_pr, dst_x, dst_y);
else if(delta_y < 0)
pw_cover(pw, win_x, win_y+mag_size_y+delta_y,
mag_size_x, -delta_y,
PIX_SRC, sample_pr,
dst_x, dst_y+mag_size_y+delta_y);
}
else
first_time = FALSE;
/*
* Compute the new destination and window positions
* for the new magnified region.
*/
sample_x = new_sample_x;
sample_y = new_sample_y;
dst_x = sample_x - (mag_size_x - sample_w)/2;
dst_y = sample_y - (mag_size_y - sample_h)/2;
win_x = dst_x + offset_x;
win_y = dst_y + offset_y;
page_x = sample_x * scale_x;
page_y = sample_y * scale_y;
if(verbose & DEBUG_MAGNIFY)
fprintf(stderr, " painting at %d %d from %d %d\n",
dst_x, dst_y, page_x, page_y);
/*
* Display the magnified region.
*/
pw_write(pw, win_x, win_y, mag_size_x, mag_size_y,
PIX_SRC, page_pr, page_x, page_y);
if(mag_border)
pw_rect(pw, win_x, win_y, mag_size_x, mag_size_y,
mag_border, PIX_SRC, -1);
/*
* Unlock
*/
pw_unlock(pw);
/*
* Read another event.
*/
window_read_event(canvas, event);
#ifdef GOBBLE_MAGNIFY
if(ioctl(canvasfd, FIONREAD, &ninputs) == 0)
while(ninputs >= sizeof(Event) &&
window_read_event(canvas, event) == 0 &&
! event_is_up(event))
ninputs -= sizeof(Event);
#endif GOBBLE_MAGNIFY
}
/*
* Ungrab all input.
*/
window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0);
/*
* Repaint
*/
pw_cover(pw, win_x, win_y, mag_size_x, mag_size_y,
PIX_SRC, sample_pr, dst_x, dst_y);
/*
* Restore the cursor.
*/
cursor_set(hand_cursor, CURSOR_OP, old_cursor_op, 0);
window_set(canvas, WIN_CURSOR, hand_cursor, 0);
}
/*
* page_pan:
* Pans page within screen.
*/
void
page_pan(canvas, pw, event)
Canvas canvas;
Pixwin *pw;
Event *event;
{
int x, y;
int dx, dy;
#ifdef GOBBLE_PAN
int ninputs, canvasfd;
#endif GOBBLE_PAN
if(sample_pr == NULL)
return;
window_set(canvas, WIN_GRAB_ALL_INPUT, TRUE, 0);
#ifdef GOBBLE_PAN
canvasfd = (int)window_get(canvas, WIN_FD);
#endif GOBBLE_PAN
do
{
x = event_x(event);
y = event_y(event);
window_read_event(canvas, event);
#ifdef GOBBLE_PAN
if(ioctl(canvasfd, FIONREAD, &ninputs) == 0)
while(ninputs >= sizeof(Event) &&
window_read_event(canvas, event) == 0 &&
! event_is_up(event))
ninputs -= sizeof(Event);
#endif GOBBLE_PAN
dx = event_x(event) - x;
dy = event_y(event) - y;
if(dx != 0 || dy != 0)
{
offset_x += dx;
offset_y += dy;
pw_cover(pw, 0, 0,
(int)window_get(canvas, WIN_WIDTH),
(int)window_get(canvas, WIN_HEIGHT),
PIX_SRC, sample_pr, -offset_x, -offset_y);
}
}
while(! event_is_up(event));
window_set(canvas, WIN_GRAB_ALL_INPUT, FALSE, 0);
}
/*
* goto_sheet:
* Opens requested sheet on screen.
*/
bool
goto_sheet(new_sheet)
int new_sheet;
{
if(! check_dvi_file())
return FALSE;
if(verbose & DEBUG_SHEET)
fprintf(stderr, "goto_sheet(%d)\n", new_sheet);
/*
* Check against page limits.
*/
if(new_sheet <= 0)
{
message("Attempt to go to sheet %d.", new_sheet);
return FALSE;
}
/*
* Are we already at the desired page ?
*/
if(file_sheet == new_sheet)
return TRUE;
/*
* Do we already know where the page is ?
*/
if(new_sheet < MAX_SHEETS && new_sheet <= last_known_sheet)
{
fseek(dvifp, sheet_table[new_sheet], 0);
file_sheet = new_sheet;
return TRUE;
}
/*
* Can't find it directly in the table:
* Go to the last known sheet...
*/
file_sheet = last_known_sheet;
fseek(dvifp, sheet_table[file_sheet], 0);
/*
* Skip through the rest of the pages to the new page.
*/
while(file_sheet < new_sheet)
{
/*
* Check for last page:
* Last page is always returned.
*/
if(last_sheet && file_sheet >= last_sheet)
{
file_sheet = last_sheet - 1;
fseek(dvifp, sheet_table[file_sheet], 0);
return TRUE;
}
/*
* Otherwise, skip this page and look at the next.
*/
process_page(SKIP);
}
return TRUE;
}
/*
* goto_page:
* Opens requested page on screen.
*/
bool
goto_page(new_page)
int new_page;
{
int sheet;
if(! check_dvi_file())
return FALSE;
if(verbose & DEBUG_SHEET)
fprintf(stderr, "goto_page(%d)\n", new_page);
/*
* Search for page in the table.
*/
for(sheet = 1; sheet < last_known_sheet; sheet++)
{
if(sheet_page[sheet] == new_page)
{
file_sheet = sheet;
fseek(dvifp, sheet_table[file_sheet], 0);
return TRUE;
}
}
/*
* Can't find it directly in the table:
* Go to the last known sheet...
*/
file_sheet = last_known_sheet;
fseek(dvifp, sheet_table[file_sheet], 0);
/*
* Skip through the rest of the pages to the new page.
*/
for( ; ; )
{
/*
* Check for last page:
*/
if(last_sheet && file_sheet >= last_sheet)
{
if(new_page == LAST_PAGE)
{
file_sheet = last_sheet - 1;
fseek(dvifp, sheet_table[file_sheet], 0);
return TRUE;
}
else
return FALSE;
}
/*
* Otherwise, examine this page.
*/
sheet = file_sheet;
process_page(SKIP);
/*
* If this was the page, go back,
* and return it.
*/
if(sheet_page[sheet] == new_page)
{
file_sheet = sheet;
fseek(dvifp, sheet_table[file_sheet], 0);
return TRUE;
}
}
}
/*
* DVI file functions.
* ==================
*/
/*
* init_dvi_file:
* Opens the dvi file, and checks for valid codes etc.
* Reads the postamble (if enabled)
* Leaves the file pointer at the start of the first page.
*/
bool
init_dvi_file()
{
int i;
/*
* Open the file; close-on-exec.
*/
if((dvifp = fopen(pathname, "r")) == NULL)
{
message("Cant open file %s", pathname);
return FALSE;
}
fcntl(fileno(dvifp), F_SETFD, 1);
/*
* Read the magic number and version number
*/
if((i = get_unsigned(dvifp, 1)) != PRE)
{
message("%s: not a dvi file.", filename);
fclose(dvifp);
return FALSE;
}
if((i = get_signed(dvifp, 1)) != DVIFORMAT)
{
message("%s: dvi format %d not supported.", filename, i);
fclose(dvifp);
return FALSE;
}
/*
* Make a note of the access time.
*/
if(fstat(fileno(dvifp), &stat_buf) == 0)
{
mtime = stat_buf.st_mtime;
}
else
{
message("%s: dvifile stat failed.", filename);
mtime = 0;
}
if(pre_load)
{
/*
* Load font information from postable.
*/
if(! read_postamble())
{
fclose(dvifp);
return FALSE;
}
/*
* Return to start of first page.
*/
fseek(dvifp, (long)14, 0);
}
else
{
/*
* Read basic data from preamble.
*/
num = get_unsigned(dvifp, 4);
den = get_unsigned(dvifp, 4);
mag = get_unsigned(dvifp, 4);
hconv = vconv = do_convert(num, den, resolution);
}
/*
* Skip i more bytes of preamble.
*/
i = get_unsigned(dvifp, 1);
fseek(dvifp, (long)i, 1);
/*
* Allocate buffer for the page.
*/
if(! (page_pr = pr_alloc(&page_mpr,
(int)(page_w * resolution), (int)(page_h * resolution), 1)))
{
message("Out of memory for image allocation.");
fclose(dvifp);
return FALSE;
}
if(verbose & DEBUG_IMSIZE)
fprintf(stderr, "Allocated buffer (%d x %d)\n",
page_pr->pr_width, page_pr->pr_height);
/*
* Set up the page fseek pointer table.
* We are now at page 0.
*/
for(i = 0; i < MAX_SHEETS; i++)
{
sheet_table[i] = 0;
sheet_page[i] = BAD_PAGE;
}
file_sheet = 1;
last_sheet = 0; /* last page == unknown */
last_known_sheet = 1;
sheet_table[last_known_sheet] = ftell(dvifp);
if(verbose & DEBUG_SHEET)
fprintf(stderr, "sheet_table[%d] = %d\n",
last_known_sheet, ftell(dvifp));
return TRUE;
}
/*
* close_dvi_file:
* Cleans up after reading a file.
*/
void
close_dvi_file()
{
if(dvifp == NULL)
return;
/*
* Get rid of image memory.
*/
sample_pr = pr_free(&sample_mpr);
page_pr = pr_free(&page_mpr);
/*
* close the dvifile.
*/
fclose(dvifp);
dvifp = NULL;
mtime = 0;
/*
* Hack the sheet numbers to prevent access to the file.
*/
last_sheet = -1;
last_known_sheet = -1;
/*
* Close the fonts and free up memory.
*/
close_fonts();
}
/*
* check_dvi_file:
* Checks that this is the same file -- has not been modified since
* it was opened.
*/
bool
check_dvi_file()
{
if(dvifp == NULL)
{
message("No dvifile open");
return FALSE;
}
if(fstat(fileno(dvifp), &stat_buf) != 0)
{
message("%s: dvifile fstat failed.", filename);
return FALSE;
}
if(stat_buf.st_mtime != mtime)
{
message("%s: dvifile modified", filename);
return FALSE;
}
return TRUE;
}
/*
* read_postamble:
* This routine is used to read in the postamble values. It
* initializes the magnification and checks the stack height prior to
* starting printing the document.
* Returns TRUE unless document cannot be processed.
*/
bool
read_postamble()
{
if(! check_dvi_file())
return FALSE;
if(! find_postamble_ptr (&postambleptr))
return FALSE;
if(get_unsigned(dvifp, 1) != POST)
{
message("%s: bad dvi file: no POST at head of postamble.",
filename);
return FALSE;
}
(void)get_unsigned(dvifp, 4); /* discard last page pointer */
num = get_unsigned(dvifp, 4);
den = get_unsigned(dvifp, 4);
mag = get_unsigned(dvifp, 4);
hconv = vconv = do_convert(num, den, resolution);
(void)get_unsigned(dvifp, 4); /* height-plus-depth of tallest page */
(void)get_unsigned(dvifp, 4); /* width of widest page */
if(get_unsigned(dvifp, 2) >= STACKSIZE)
{
message("%s: bad dvi file: stack is too large.",
filename);
return FALSE;
}
/* last_sheet = */ get_unsigned(dvifp, 2);
if(! get_font_def())
return FALSE;
return TRUE;
}
/*
* find_postamble_ptr
* Move to the end of the dvifile and find the start of the postamble.
*/
bool
find_postamble_ptr(postambleptr)
long *postambleptr;
{
int i;
fseek(dvifp, (long) 0, 2);
*postambleptr = ftell(dvifp) - 4;
fseek(dvifp, *postambleptr, 0);
for( ; ; )
{
fseek(dvifp, --(*postambleptr), 0);
if(((i = get_unsigned(dvifp, 1)) != 223) && (i != DVIFORMAT))
{
message("%s: Bad dvi file: bad end of file", filename);
return FALSE;
}
if(i == DVIFORMAT)
break;
}
fseek(dvifp, (*postambleptr) - 4, 0);
*postambleptr = get_unsigned(dvifp, 4);
fseek(dvifp, *postambleptr, 0);
return TRUE;
}
/*
* process_page:
* Rasterises the next page in the dvifile into page_mpr.
* Leaves the file pointer at the start of the next page.
*
* If skip mode is true, then nothing is actually drawn, the commands
* are interpreted only for the side effect of moving the filepointer
* to the next page.
*/
bool
process_page(skip_mode)
register bool skip_mode;
{
int command; /* current command */
register int i; /* command parameter; loop index */
int k; /* temporary parameter */
int val, val2; /* temporarys to hold command information*/
int w; /* current horizontal spacing */
int x; /* current horizontal spacing */
int y; /* current vertical spacing */
int z; /* current vertical spacing */
int counter[10];
int sp; /* stack pointer */
static struct stack_entry stack[STACKSIZE]; /* stack */
if(! check_dvi_file())
return FALSE;
if(verbose & DEBUG_SHEET)
fprintf(stderr, "sheet %d starts at %d\n",
file_sheet, ftell(dvifp));
while((command = get_unsigned(dvifp, 1)) != EOP)
{
switch(command)
{
case SET1:
case SET2:
case SET3:
case SET4:
val = get_unsigned(dvifp, command-SET1+1);
if(! skip_mode)
set_char(val, command);
break;
case SET_RULE:
val = get_unsigned(dvifp, 4);
val2 = get_unsigned(dvifp, 4);
if(! skip_mode)
set_rule(val, val2, 1);
break;
case PUT1:
case PUT2:
case PUT3:
case PUT4:
val = get_unsigned(dvifp,command-PUT1+1);
if(! skip_mode)
set_char(val, command);
break;
case PUT_RULE:
val = get_unsigned(dvifp, 4);
val2 = get_unsigned(dvifp, 4);
if(! skip_mode)
set_rule(val, val2, 0);
break;
case NOP:
break;
case BOP:
/*
* These are the 10 counters.
* Discard previous page pointer.
*/
for(i=0; i<10; i++)
counter[i] = get_unsigned(dvifp, 4);
(void)get_unsigned(dvifp, 4);
/*
* The first counter is the page number.
*/
disp_page = counter[0];
if(file_sheet < MAX_SHEETS)
sheet_page[file_sheet] = disp_page;
/*
* Show what is happening.
*/
sprintf(label, "%s: File \"%s\" Page %d %s",
DVIPAGE_LABEL, filename,
disp_page, (skip_mode) ? "Skipping" : "Processing");
window_set(disp_frame,
FRAME_LABEL, label,
0);
if(! skip_mode)
{
/*
* Clear the page
*/
pr_rop(page_pr, 0, 0,
page_pr->pr_width, page_pr->pr_height,
PIX_CLR, NULL, 0, 0);
/*
* Mark the edges of the page
*/
pr_rect(page_pr, 0, 0,
(int)(page_w * resolution),
(int)(page_h * resolution),
3, PIX_SET, 1);
/*
* Mark the nominal page window.
*/
if(show_page_frame)
{
pr_rect(page_pr, 0+origin_x, 0+origin_y,
(int)(page_w*resolution) - 2*origin_x,
(int)(page_h*resolution) - 2*origin_y,
1, PIX_SET, 1);
}
}
h = v = w = x = y = z = 0;
sp = 0;
fontptr = NULL;
break;
case PUSH:
if (sp >= STACKSIZE)
{
message("%s: Bad dvi file: stack overflow",
filename);
return FALSE;
}
stack[sp].h = h;
stack[sp].v = v;
stack[sp].w = w;
stack[sp].x = x;
stack[sp].y = y;
stack[sp].z = z;
sp++;
break;
case POP:
--sp;
if (sp < 0)
{
message("%s: Bad dvi file: stack underflow",
filename);
return FALSE;
}
h = stack[sp].h;
v = stack[sp].v;
w = stack[sp].w;
x = stack[sp].x;
y = stack[sp].y;
z = stack[sp].z;
break;
case RIGHT1:
case RIGHT2:
case RIGHT3:
case RIGHT4:
val = get_signed(dvifp,command-RIGHT1+1);
if(! skip_mode)
move_over(val);
break;
case W0:
if(! skip_mode)
move_over(w);
break;
case W1:
case W2:
case W3:
case W4:
w = get_signed(dvifp,command-W1+1);
if(! skip_mode)
move_over(w);
break;
case X0:
if(! skip_mode)
move_over(x);
break;
case X1:
case X2:
case X3:
case X4:
x = get_signed(dvifp,command-X1+1);
if(! skip_mode)
move_over(x);
break;
case DOWN1:
case DOWN2:
case DOWN3:
case DOWN4:
val = get_signed(dvifp,command-DOWN1+1);
if(! skip_mode)
move_down(val);
break;
case Y0:
if(! skip_mode)
move_down(y);
break;
case Y1:
case Y2:
case Y3:
case Y4:
y = get_signed(dvifp,command-Y1+1);
if(! skip_mode)
move_down(y);
break;
case Z0:
if(! skip_mode)
move_down(z);
break;
case Z1:
case Z2:
case Z3:
case Z4:
z = get_signed(dvifp,command-Z1+1);
if(! skip_mode)
move_down(z);
break;
case FNT1:
case FNT2:
case FNT3:
case FNT4:
if(! skip_mode)
set_font_num(
get_unsigned(dvifp,command-FNT1+1));
break;
case XXX1:
case XXX2:
case XXX3:
case XXX4:
k = get_unsigned(dvifp,command-XXX1+1);
while(k--)
get_unsigned(dvifp, 1);
break;
case FNT_DEF1:
case FNT_DEF2:
case FNT_DEF3:
case FNT_DEF4:
if(pre_load)
skip_font_def(
get_unsigned(dvifp, command-FNT_DEF1+1));
else
if(! read_font_def(
get_unsigned(dvifp, command-FNT_DEF1+1)))
return FALSE;
break;
case PRE:
message(
"%s: Bad dvi file: preamble found within main section.",
filename);
return FALSE;
case POST:
fseek(dvifp, (long) -1, 1);
last_sheet = file_sheet;
/*
* We have done nothing, so there is no need to
* resample the page or increment the page counter.
*/
return FALSE;
case POST_POST:
message(
"%s: Bad dvi file: postpostamble found within main section.",
filename);
return FALSE;
default:
if(command >= FONT_00 && command <= FONT_63)
{
if(! skip_mode)
set_font_num(command - FONT_00);
}
else if(command >= SETC_000 && command <= SETC_127)
{
if(! skip_mode)
set_char(command - SETC_000, command);
}
else
{
message(
"%s: Bad dvi file: undefined command (%d) found.",
filename, command);
return FALSE;
}
}
}
/*
* End of page.
*/
if(! skip_mode)
{
/*
* Sample the page.
*/
sample_page();
disp_sheet = file_sheet;
}
/*
* The file is now at the start of the next page.
*/
file_sheet++;
if(file_sheet > last_known_sheet)
{
if(file_sheet < MAX_SHEETS)
{
last_known_sheet = file_sheet;
sheet_table[file_sheet] = ftell(dvifp);
}
if(verbose & DEBUG_SHEET)
fprintf(stderr, "sheet %d starts at %d\n",
file_sheet, ftell(dvifp));
}
return TRUE;
}
/*
* Draw and Move Functions.
* ========================
*/
/*
* set_font_num:
* This routine is used to specify the font to be used in printing future
* chars.
*/
void
set_font_num(k)
int k;
{
for(fontptr = hfontptr; fontptr != NULL; fontptr = fontptr->next)
{
if(fontptr->k == k)
{
fontptr->use_count++;
return;
}
}
fprintf(stderr, "I have lost a font; this cant happen\n");
exit(1);
}
/*
* set_char:
*/
void
set_char(c, command)
int c, command;
{
register struct char_entry *ptr;
ptr = &(fontptr->ch[c]);
hh = Pix_round(h, hconv);
vv = Pix_round(v, vconv);
if(! ptr->where.isloaded)
if(! load_char(fontptr, ptr))
return;
if(ptr->where.address.pixrectptr)
pr_rop(page_pr, hh - ptr->xOffset + origin_x,
vv - ptr->yOffset + origin_y,
ptr->width, ptr->height, PIX_SRC | PIX_DST,
ptr->where.address.pixrectptr, 0, 0);
if(command <= SET4)
h += ptr->tfmw;
return;
}
/*
* set_rule:
* This routine will draw a rule on the screen
*/
void
set_rule(a, b, Set)
int a, b;
bool Set;
{
int ehh, evv;
hh = Pix_round(h, hconv);
vv = Pix_round(v - a, vconv);
ehh = Pix_round(h + b, hconv);
evv = Pix_round(v, vconv);
if(hh == ehh)
ehh++;
if(vv == evv)
vv--;
if((a > 0) && (b > 0))
pr_rop(page_pr, hh+origin_x, vv+origin_y,
ehh-hh, evv-vv, PIX_SET, NULL, 0, 0);
if(Set)
{
h += b;
/* v += a; */
}
}
/*
* move_down:
*/
void
move_down(a)
int a;
{
v += a;
}
/*
* move_over:
*/
void
move_over(b)
int b;
{
h += b;
}